﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace _2dTo3D
{
    public partial class ConvertBmpToScad : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
		{
			var invert = cbxInvert.Checked;
            var depth = Int32.Parse(ddlDepth.SelectedValue);
            var pixelMultiplier = Double.Parse(ddlPixelMultiplier.SelectedValue);
            if (fulImage.HasFile)
            {
                string fileExt = System.IO.Path.GetExtension(fulImage.FileName);
                if ("|.gif|.png|.jpeg|.jpg|.ico|.icon|".Contains("|" + fileExt + "|"))
                {

                    Bitmap img = new Bitmap(fulImage.FileContent);
                    if (img.Height > 130)
                        throw new Exception("Height limit 130px");

                    if (img.Width > 130)
                        throw new Exception("Width limit 130px");


					Boolean[,] bitmap = new Boolean[img.Width,img.Height];

                    Response.Clear();
                    Response.ContentType = "application/sla";
                    Response.AddHeader("content-disposition", String.Format("attachment;filename={0}.scad", fulImage.FileName.Replace(fileExt, String.Empty)));


					Response.Write("\n\tunion() {");	

                    var yMax = img.Height * pixelMultiplier;
                    if (yMax % 2 != 0)
                        yMax = img.Height + 1;
  

                    var yMaxCentered = (yMax / 2);
                    var yMinCentered = yMaxCentered - yMax;

                    var xMax = img.Width * pixelMultiplier;
                    if (xMax % 2 != 0)
                        xMax = img.Width + 1;

                    var xMaxCentered = (xMax / 2);
                    var xMinCentered = xMaxCentered - xMax;

                    var y = yMinCentered;
                    var yCoord = img.Height-1;

	                int explodeLevels = 0;
					while (yCoord >= 0)
                    {
                            y = y + pixelMultiplier;
                            var x = xMinCentered;
                            var xCoord = 0;

							while (xCoord < img.Width)
							{
								x = x + pixelMultiplier;
								if (bitmap[xCoord, yCoord])
								{
									xCoord++;
		                            continue;
	                            }

								//** Uncomment this line to see levels **//
								explodeLevels ++;
								//try
								//{
									double pixelPercentWhite = PercentWhite(xCoord, yCoord, img);

									double pixelPositionX =  x + pixelMultiplier;
									double pixelPositioneY = y + pixelMultiplier;
									double pixelPositionZ = 0;

									int xColorMatches = MatchesX(xCoord, yCoord, pixelPercentWhite, img, bitmap);
									int yColorMatches = MatchesY(xCoord, yCoord, pixelPercentWhite, img, bitmap);

									int xCompression = 1;
									int yCompression = 1;
									if (xColorMatches > 0 || yColorMatches > 0)
									{
										bool endCompressionBlock = false;
										if (xColorMatches > yColorMatches)
										{
											xCompression = xColorMatches;

											int yBitmap = yCoord;
											while (yBitmap >= 0 && xColorMatches == MatchesX(xCoord, yBitmap, pixelPercentWhite, img, bitmap))
											{
												yCompression ++;
												for (int xBitmap = xCoord; xBitmap < xCoord + xColorMatches; xBitmap++)
												{
													if (bitmap[xBitmap, yBitmap])
													{
														break;
													}
													bitmap[xBitmap, yBitmap] = true;
												}
												yBitmap--;
											}
											yCompression--;
										}
										else
										{
											yCompression = yColorMatches;
											int xBitmap = xCoord - 1;
											while (xBitmap < img.Width - 1 && yColorMatches == MatchesY(xBitmap+1, yCoord, pixelPercentWhite, img, bitmap))
											{
												xBitmap++;
												xCompression++;
												for (int yBitmap = yCoord; yBitmap >= (yCoord + 1) - yColorMatches; yBitmap--)
												{
													if (bitmap[xBitmap, yBitmap])
													{
														break;
													}
													bitmap[xBitmap, yBitmap] = true;
												}
											}
											xCompression--;
										}
									}
									else
									{
										bitmap[yCoord - 1, yCoord] = true;
									}

									double pixelSizeX = pixelMultiplier * xCompression ;
									double pixelSizeY = pixelMultiplier * yCompression;
									double pixelSizeZ = (depth * pixelMultiplier) * ((invert) ? 1 - pixelPercentWhite:pixelPercentWhite);

									Response.Write(String.Format("\n\t\ttranslate ([{0},{1},{2}]){{", pixelPositionX,
										pixelPositioneY, pixelPositionZ + explodeLevels));
									Response.Write(String.Format("\n\t\t\tcube ([{0},{1},{2}]); \n", pixelSizeX,
										pixelSizeY, pixelSizeZ));
		                            Response.Write(String.Format("\n\t\t }}"));
								//}
								//catch (Exception ex)
								//{
								//	//Don't care
								//}
                                xCoord++;
                            }
                            Response.Flush();
                            yCoord--;
                        }
                        Response.Flush();
					}
					Response.Write("\n}");
                    Response.End();
                }
            }


		protected double PercentWhite(Int32 xCoord, Int32 yCoord, Bitmap img)
		{
			var color = img.GetPixel(xCoord, yCoord);
			double lightnessOfPixel = color.R + color.G + color.B;
			if (Math.Round(lightnessOfPixel, 10) == 0D)
			{
				return 0;
			}
			double percentWhite = ((768D - lightnessOfPixel) / 768D);
			double percentBlack = 1 - percentWhite;
			return Math.Round(percentBlack, 1, MidpointRounding.AwayFromZero);
		}

		protected int MatchesX(Int32 xCoord, Int32 yCoord, Double percentWhite, Bitmap img, Boolean[,] bitmap)
		{

			int xColorMatches = 0;
			while (xCoord + xColorMatches < img.Width && percentWhite == PercentWhite(xCoord + xColorMatches, yCoord, img) && !bitmap[xCoord + xColorMatches, yCoord])
			{
				xColorMatches++;
			}
			return xColorMatches;
		}
		protected int MatchesY(Int32 xCoord, Int32 yCoord, Double percentWhite, Bitmap img, Boolean[,] bitmap)
		{
			int yColorMatches = 0;
			while (yCoord - yColorMatches >= 0 && percentWhite == PercentWhite(xCoord, yCoord - yColorMatches, img) && !bitmap[xCoord,yCoord - yColorMatches])
			{
				yColorMatches++;
			}
			return yColorMatches;
		}

        protected void fulImage_Unload(object sender, EventArgs e)
        {

        }
    }
}